home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / lib / python2.6 / cgi.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2009-11-11  |  33KB  |  1,132 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''Support module for CGI (Common Gateway Interface) scripts.
  5.  
  6. This module defines a number of utilities for use by CGI scripts
  7. written in Python.
  8. '''
  9. __version__ = '2.6'
  10. from operator import attrgetter
  11. import sys
  12. import os
  13. import urllib
  14. import UserDict
  15. import urlparse
  16. from warnings import filterwarnings, catch_warnings, warn
  17. catch_warnings().__enter__()
  18.  
  19. try:
  20.     import mimetools
  21.     if sys.py3kwarning:
  22.         filterwarnings('ignore', '.*rfc822 has been removed', DeprecationWarning)
  23.     
  24.     import rfc822
  25. finally:
  26.     pass
  27.  
  28.  
  29. try:
  30.     from cStringIO import StringIO
  31. except ImportError:
  32.     catch_warnings().__exit__
  33.     catch_warnings().__exit__
  34.     catch_warnings()
  35.     from StringIO import StringIO
  36. except:
  37.     catch_warnings().__exit__
  38.  
  39. __all__ = [
  40.     'MiniFieldStorage',
  41.     'FieldStorage',
  42.     'FormContentDict',
  43.     'SvFormContentDict',
  44.     'InterpFormContentDict',
  45.     'FormContent',
  46.     'parse',
  47.     'parse_qs',
  48.     'parse_qsl',
  49.     'parse_multipart',
  50.     'parse_header',
  51.     'print_exception',
  52.     'print_environ',
  53.     'print_form',
  54.     'print_directory',
  55.     'print_arguments',
  56.     'print_environ_usage',
  57.     'escape']
  58. logfile = ''
  59. logfp = None
  60.  
  61. def initlog(*allargs):
  62.     '''Write a log message, if there is a log file.
  63.  
  64.     Even though this function is called initlog(), you should always
  65.     use log(); log is a variable that is set either to initlog
  66.     (initially), to dolog (once the log file has been opened), or to
  67.     nolog (when logging is disabled).
  68.  
  69.     The first argument is a format string; the remaining arguments (if
  70.     any) are arguments to the % operator, so e.g.
  71.         log("%s: %s", "a", "b")
  72.     will write "a: b" to the log file, followed by a newline.
  73.  
  74.     If the global logfp is not None, it should be a file object to
  75.     which log data is written.
  76.  
  77.     If the global logfp is None, the global logfile may be a string
  78.     giving a filename to open, in append mode.  This file should be
  79.     world writable!!!  If the file can\'t be opened, logging is
  80.     silently disabled (since there is no safe place where we could
  81.     send an error message).
  82.  
  83.     '''
  84.     global logfp, log
  85.     if logfile and not logfp:
  86.         
  87.         try:
  88.             logfp = open(logfile, 'a')
  89.         except IOError:
  90.             pass
  91.         except:
  92.             None<EXCEPTION MATCH>IOError
  93.         
  94.  
  95.     None<EXCEPTION MATCH>IOError
  96.     if not logfp:
  97.         log = nolog
  98.     else:
  99.         log = dolog
  100.     log(*allargs)
  101.  
  102.  
  103. def dolog(fmt, *args):
  104.     '''Write a log message to the log file.  See initlog() for docs.'''
  105.     logfp.write(fmt % args + '\n')
  106.  
  107.  
  108. def nolog(*allargs):
  109.     '''Dummy function, assigned to log when logging is disabled.'''
  110.     pass
  111.  
  112. log = initlog
  113. maxlen = 0
  114.  
  115. def parse(fp = None, environ = os.environ, keep_blank_values = 0, strict_parsing = 0):
  116.     '''Parse a query in the environment or from a file (default stdin)
  117.  
  118.         Arguments, all optional:
  119.  
  120.         fp              : file pointer; default: sys.stdin
  121.  
  122.         environ         : environment dictionary; default: os.environ
  123.  
  124.         keep_blank_values: flag indicating whether blank values in
  125.             URL encoded forms should be treated as blank strings.
  126.             A true value indicates that blanks should be retained as
  127.             blank strings.  The default false value indicates that
  128.             blank values are to be ignored and treated as if they were
  129.             not included.
  130.  
  131.         strict_parsing: flag indicating what to do with parsing errors.
  132.             If false (the default), errors are silently ignored.
  133.             If true, errors raise a ValueError exception.
  134.     '''
  135.     if fp is None:
  136.         fp = sys.stdin
  137.     
  138.     if 'REQUEST_METHOD' not in environ:
  139.         environ['REQUEST_METHOD'] = 'GET'
  140.     
  141.     if environ['REQUEST_METHOD'] == 'POST':
  142.         (ctype, pdict) = parse_header(environ['CONTENT_TYPE'])
  143.         if ctype == 'multipart/form-data':
  144.             return parse_multipart(fp, pdict)
  145.         if ctype == 'application/x-www-form-urlencoded':
  146.             clength = int(environ['CONTENT_LENGTH'])
  147.             if maxlen and clength > maxlen:
  148.                 raise ValueError, 'Maximum content length exceeded'
  149.             clength > maxlen
  150.             qs = fp.read(clength)
  151.         else:
  152.             qs = ''
  153.         if 'QUERY_STRING' in environ:
  154.             if qs:
  155.                 qs = qs + '&'
  156.             
  157.             qs = qs + environ['QUERY_STRING']
  158.         elif sys.argv[1:]:
  159.             if qs:
  160.                 qs = qs + '&'
  161.             
  162.             qs = qs + sys.argv[1]
  163.         
  164.         environ['QUERY_STRING'] = qs
  165.     elif 'QUERY_STRING' in environ:
  166.         qs = environ['QUERY_STRING']
  167.     elif sys.argv[1:]:
  168.         qs = sys.argv[1]
  169.     else:
  170.         qs = ''
  171.     environ['QUERY_STRING'] = qs
  172.     return parse_qs(qs, keep_blank_values, strict_parsing)
  173.  
  174.  
  175. def parse_qs(qs, keep_blank_values = 0, strict_parsing = 0):
  176.     '''Parse a query given as a string argument.'''
  177.     warn('cgi.parse_qs is deprecated, use urlparse.parse_qs             instead', PendingDeprecationWarning, 2)
  178.     return urlparse.parse_qs(qs, keep_blank_values, strict_parsing)
  179.  
  180.  
  181. def parse_qsl(qs, keep_blank_values = 0, strict_parsing = 0):
  182.     '''Parse a query given as a string argument.'''
  183.     warn('cgi.parse_qsl is deprecated, use urlparse.parse_qsl instead', PendingDeprecationWarning, 2)
  184.     return urlparse.parse_qsl(qs, keep_blank_values, strict_parsing)
  185.  
  186.  
  187. def parse_multipart(fp, pdict):
  188.     '''Parse multipart input.
  189.  
  190.     Arguments:
  191.     fp   : input file
  192.     pdict: dictionary containing other parameters of content-type header
  193.  
  194.     Returns a dictionary just like parse_qs(): keys are the field names, each
  195.     value is a list of values for that field.  This is easy to use but not
  196.     much good if you are expecting megabytes to be uploaded -- in that case,
  197.     use the FieldStorage class instead which is much more flexible.  Note
  198.     that content-type is the raw, unparsed contents of the content-type
  199.     header.
  200.  
  201.     XXX This does not parse nested multipart parts -- use FieldStorage for
  202.     that.
  203.  
  204.     XXX This should really be subsumed by FieldStorage altogether -- no
  205.     point in having two implementations of the same parsing algorithm.
  206.     Also, FieldStorage protects itself better against certain DoS attacks
  207.     by limiting the size of the data read in one chunk.  The API here
  208.     does not support that kind of protection.  This also affects parse()
  209.     since it can call parse_multipart().
  210.  
  211.     '''
  212.     boundary = ''
  213.     if 'boundary' in pdict:
  214.         boundary = pdict['boundary']
  215.     
  216.     if not valid_boundary(boundary):
  217.         raise ValueError, 'Invalid boundary in multipart form: %r' % (boundary,)
  218.     valid_boundary(boundary)
  219.     nextpart = '--' + boundary
  220.     lastpart = '--' + boundary + '--'
  221.     partdict = { }
  222.     terminator = ''
  223.     while terminator != lastpart:
  224.         bytes = -1
  225.         data = None
  226.         if terminator:
  227.             headers = mimetools.Message(fp)
  228.             clength = headers.getheader('content-length')
  229.             if clength:
  230.                 
  231.                 try:
  232.                     bytes = int(clength)
  233.                 except ValueError:
  234.                     pass
  235.                 except:
  236.                     None<EXCEPTION MATCH>ValueError
  237.                 
  238.  
  239.             None<EXCEPTION MATCH>ValueError
  240.             if bytes > 0:
  241.                 if maxlen and bytes > maxlen:
  242.                     raise ValueError, 'Maximum content length exceeded'
  243.                 bytes > maxlen
  244.                 data = fp.read(bytes)
  245.             else:
  246.                 data = ''
  247.         
  248.         lines = []
  249.         while None:
  250.             line = fp.readline()
  251.             if not line:
  252.                 terminator = lastpart
  253.                 break
  254.             
  255.             if line[:2] == '--':
  256.                 terminator = line.strip()
  257.                 if terminator in (nextpart, lastpart):
  258.                     break
  259.                 
  260.             
  261.             continue
  262.             if data is None:
  263.                 continue
  264.             
  265.         if bytes < 0:
  266.             if lines:
  267.                 line = lines[-1]
  268.                 if line[-2:] == '\r\n':
  269.                     line = line[:-2]
  270.                 elif line[-1:] == '\n':
  271.                     line = line[:-1]
  272.                 
  273.                 lines[-1] = line
  274.                 data = ''.join(lines)
  275.             
  276.         
  277.         line = headers['content-disposition']
  278.         if not line:
  279.             continue
  280.         
  281.         (key, params) = parse_header(line)
  282.         if key != 'form-data':
  283.             continue
  284.         
  285.         if 'name' in params:
  286.             name = params['name']
  287.         
  288.         if name in partdict:
  289.             partdict[name].append(data)
  290.             continue
  291.         'name' in params
  292.         partdict[name] = [
  293.             data]
  294.     return partdict
  295.  
  296.  
  297. def _parseparam(s):
  298.     while s[:1] == ';':
  299.         s = s[1:]
  300.         end = s.find(';')
  301.         while end > 0 and s.count('"', 0, end) % 2:
  302.             end = s.find(';', end + 1)
  303.         if end < 0:
  304.             end = len(s)
  305.         
  306.         f = s[:end]
  307.         yield f.strip()
  308.         s = s[end:]
  309.  
  310.  
  311. def parse_header(line):
  312.     '''Parse a Content-type like header.
  313.  
  314.     Return the main content-type and a dictionary of options.
  315.  
  316.     '''
  317.     parts = _parseparam(';' + line)
  318.     key = parts.next()
  319.     pdict = { }
  320.     for p in parts:
  321.         i = p.find('=')
  322.         if i >= 0:
  323.             name = p[:i].strip().lower()
  324.             value = p[i + 1:].strip()
  325.             if len(value) >= 2:
  326.                 if value[-1] == value[-1]:
  327.                     pass
  328.                 elif value[-1] == '"':
  329.                     value = value[1:-1]
  330.                     value = value.replace('\\\\', '\\').replace('\\"', '"')
  331.                 
  332.             pdict[name] = value
  333.             continue
  334.         value[0]
  335.     
  336.     return (key, pdict)
  337.  
  338.  
  339. class MiniFieldStorage:
  340.     '''Like FieldStorage, for use when no file uploads are possible.'''
  341.     filename = None
  342.     list = None
  343.     type = None
  344.     file = None
  345.     type_options = { }
  346.     disposition = None
  347.     disposition_options = { }
  348.     headers = { }
  349.     
  350.     def __init__(self, name, value):
  351.         '''Constructor from field name and value.'''
  352.         self.name = name
  353.         self.value = value
  354.  
  355.     
  356.     def __repr__(self):
  357.         '''Return printable representation.'''
  358.         return 'MiniFieldStorage(%r, %r)' % (self.name, self.value)
  359.  
  360.  
  361.  
  362. class FieldStorage:
  363.     """Store a sequence of fields, reading multipart/form-data.
  364.  
  365.     This class provides naming, typing, files stored on disk, and
  366.     more.  At the top level, it is accessible like a dictionary, whose
  367.     keys are the field names.  (Note: None can occur as a field name.)
  368.     The items are either a Python list (if there's multiple values) or
  369.     another FieldStorage or MiniFieldStorage object.  If it's a single
  370.     object, it has the following attributes:
  371.  
  372.     name: the field name, if specified; otherwise None
  373.  
  374.     filename: the filename, if specified; otherwise None; this is the
  375.         client side filename, *not* the file name on which it is
  376.         stored (that's a temporary file you don't deal with)
  377.  
  378.     value: the value as a *string*; for file uploads, this
  379.         transparently reads the file every time you request the value
  380.  
  381.     file: the file(-like) object from which you can read the data;
  382.         None if the data is stored a simple string
  383.  
  384.     type: the content-type, or None if not specified
  385.  
  386.     type_options: dictionary of options specified on the content-type
  387.         line
  388.  
  389.     disposition: content-disposition, or None if not specified
  390.  
  391.     disposition_options: dictionary of corresponding options
  392.  
  393.     headers: a dictionary(-like) object (sometimes rfc822.Message or a
  394.         subclass thereof) containing *all* headers
  395.  
  396.     The class is subclassable, mostly for the purpose of overriding
  397.     the make_file() method, which is called internally to come up with
  398.     a file open for reading and writing.  This makes it possible to
  399.     override the default choice of storing all files in a temporary
  400.     directory and unlinking them as soon as they have been opened.
  401.  
  402.     """
  403.     
  404.     def __init__(self, fp = None, headers = None, outerboundary = '', environ = os.environ, keep_blank_values = 0, strict_parsing = 0):
  405.         '''Constructor.  Read multipart/* until last part.
  406.  
  407.         Arguments, all optional:
  408.  
  409.         fp              : file pointer; default: sys.stdin
  410.             (not used when the request method is GET)
  411.  
  412.         headers         : header dictionary-like object; default:
  413.             taken from environ as per CGI spec
  414.  
  415.         outerboundary   : terminating multipart boundary
  416.             (for internal use only)
  417.  
  418.         environ         : environment dictionary; default: os.environ
  419.  
  420.         keep_blank_values: flag indicating whether blank values in
  421.             URL encoded forms should be treated as blank strings.
  422.             A true value indicates that blanks should be retained as
  423.             blank strings.  The default false value indicates that
  424.             blank values are to be ignored and treated as if they were
  425.             not included.
  426.  
  427.         strict_parsing: flag indicating what to do with parsing errors.
  428.             If false (the default), errors are silently ignored.
  429.             If true, errors raise a ValueError exception.
  430.  
  431.         '''
  432.         method = 'GET'
  433.         self.keep_blank_values = keep_blank_values
  434.         self.strict_parsing = strict_parsing
  435.         if 'REQUEST_METHOD' in environ:
  436.             method = environ['REQUEST_METHOD'].upper()
  437.         
  438.         self.qs_on_post = None
  439.         if method == 'GET' or method == 'HEAD':
  440.             if 'QUERY_STRING' in environ:
  441.                 qs = environ['QUERY_STRING']
  442.             elif sys.argv[1:]:
  443.                 qs = sys.argv[1]
  444.             else:
  445.                 qs = ''
  446.             fp = StringIO(qs)
  447.             if headers is None:
  448.                 headers = {
  449.                     'content-type': 'application/x-www-form-urlencoded' }
  450.             
  451.         
  452.         if headers is None:
  453.             headers = { }
  454.             if method == 'POST':
  455.                 headers['content-type'] = 'application/x-www-form-urlencoded'
  456.             
  457.             if 'CONTENT_TYPE' in environ:
  458.                 headers['content-type'] = environ['CONTENT_TYPE']
  459.             
  460.             if 'QUERY_STRING' in environ:
  461.                 self.qs_on_post = environ['QUERY_STRING']
  462.             
  463.             if 'CONTENT_LENGTH' in environ:
  464.                 headers['content-length'] = environ['CONTENT_LENGTH']
  465.             
  466.         
  467.         if not fp:
  468.             pass
  469.         self.fp = sys.stdin
  470.         self.headers = headers
  471.         self.outerboundary = outerboundary
  472.         cdisp = ''
  473.         pdict = { }
  474.         if 'content-disposition' in self.headers:
  475.             (cdisp, pdict) = parse_header(self.headers['content-disposition'])
  476.         
  477.         self.disposition = cdisp
  478.         self.disposition_options = pdict
  479.         self.name = None
  480.         if 'name' in pdict:
  481.             self.name = pdict['name']
  482.         
  483.         self.filename = None
  484.         if 'filename' in pdict:
  485.             self.filename = pdict['filename']
  486.         
  487.         if 'content-type' in self.headers:
  488.             (ctype, pdict) = parse_header(self.headers['content-type'])
  489.         elif self.outerboundary or method != 'POST':
  490.             ctype = 'text/plain'
  491.             pdict = { }
  492.         else:
  493.             ctype = 'application/x-www-form-urlencoded'
  494.             pdict = { }
  495.         self.type = ctype
  496.         self.type_options = pdict
  497.         self.innerboundary = ''
  498.         if 'boundary' in pdict:
  499.             self.innerboundary = pdict['boundary']
  500.         
  501.         clen = -1
  502.         if 'content-length' in self.headers:
  503.             
  504.             try:
  505.                 clen = int(self.headers['content-length'])
  506.             except ValueError:
  507.                 pass
  508.  
  509.             if maxlen and clen > maxlen:
  510.                 raise ValueError, 'Maximum content length exceeded'
  511.             clen > maxlen
  512.         
  513.         self.length = clen
  514.         self.list = None
  515.         self.file = None
  516.         self.done = 0
  517.         if ctype == 'application/x-www-form-urlencoded':
  518.             self.read_urlencoded()
  519.         elif ctype[:10] == 'multipart/':
  520.             self.read_multi(environ, keep_blank_values, strict_parsing)
  521.         else:
  522.             self.read_single()
  523.  
  524.     
  525.     def __repr__(self):
  526.         '''Return a printable representation.'''
  527.         return 'FieldStorage(%r, %r, %r)' % (self.name, self.filename, self.value)
  528.  
  529.     
  530.     def __iter__(self):
  531.         return iter(self.keys())
  532.  
  533.     
  534.     def __getattr__(self, name):
  535.         if name != 'value':
  536.             raise AttributeError, name
  537.         name != 'value'
  538.         if self.file:
  539.             self.file.seek(0)
  540.             value = self.file.read()
  541.             self.file.seek(0)
  542.         elif self.list is not None:
  543.             value = self.list
  544.         else:
  545.             value = None
  546.         return value
  547.  
  548.     
  549.     def __getitem__(self, key):
  550.         '''Dictionary style indexing.'''
  551.         if self.list is None:
  552.             raise TypeError, 'not indexable'
  553.         self.list is None
  554.         found = []
  555.         for item in self.list:
  556.             if item.name == key:
  557.                 found.append(item)
  558.                 continue
  559.         
  560.         if not found:
  561.             raise KeyError, key
  562.         found
  563.         if len(found) == 1:
  564.             return found[0]
  565.         return found
  566.  
  567.     
  568.     def getvalue(self, key, default = None):
  569.         """Dictionary style get() method, including 'value' lookup."""
  570.         if key in self:
  571.             value = self[key]
  572.             if type(value) is type([]):
  573.                 return map(attrgetter('value'), value)
  574.             return value.value
  575.         key in self
  576.         return default
  577.  
  578.     
  579.     def getfirst(self, key, default = None):
  580.         ''' Return the first value received.'''
  581.         if key in self:
  582.             value = self[key]
  583.             if type(value) is type([]):
  584.                 return value[0].value
  585.             return value.value
  586.         key in self
  587.         return default
  588.  
  589.     
  590.     def getlist(self, key):
  591.         ''' Return list of received values.'''
  592.         if key in self:
  593.             value = self[key]
  594.             if type(value) is type([]):
  595.                 return map(attrgetter('value'), value)
  596.             return [
  597.                 value.value]
  598.         key in self
  599.         return []
  600.  
  601.     
  602.     def keys(self):
  603.         '''Dictionary style keys() method.'''
  604.         if self.list is None:
  605.             raise TypeError, 'not indexable'
  606.         self.list is None
  607.         return list(set((lambda .0: for item in .0:
  608. item.name)(self.list)))
  609.  
  610.     
  611.     def has_key(self, key):
  612.         '''Dictionary style has_key() method.'''
  613.         if self.list is None:
  614.             raise TypeError, 'not indexable'
  615.         self.list is None
  616.         return (any,)((lambda .0: for item in .0:
  617. item.name == key)(self.list))
  618.  
  619.     
  620.     def __contains__(self, key):
  621.         '''Dictionary style __contains__ method.'''
  622.         if self.list is None:
  623.             raise TypeError, 'not indexable'
  624.         self.list is None
  625.         return (any,)((lambda .0: for item in .0:
  626. item.name == key)(self.list))
  627.  
  628.     
  629.     def __len__(self):
  630.         '''Dictionary style len(x) support.'''
  631.         return len(self.keys())
  632.  
  633.     
  634.     def __nonzero__(self):
  635.         return bool(self.list)
  636.  
  637.     
  638.     def read_urlencoded(self):
  639.         '''Internal: read data in query string format.'''
  640.         qs = self.fp.read(self.length)
  641.         if self.qs_on_post:
  642.             qs += '&' + self.qs_on_post
  643.         
  644.         self.list = list = []
  645.         for key, value in urlparse.parse_qsl(qs, self.keep_blank_values, self.strict_parsing):
  646.             list.append(MiniFieldStorage(key, value))
  647.         
  648.         self.skip_lines()
  649.  
  650.     FieldStorageClass = None
  651.     
  652.     def read_multi(self, environ, keep_blank_values, strict_parsing):
  653.         '''Internal: read a part that is itself multipart.'''
  654.         ib = self.innerboundary
  655.         if not valid_boundary(ib):
  656.             raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,)
  657.         valid_boundary(ib)
  658.         self.list = []
  659.         if self.qs_on_post:
  660.             for key, value in urlparse.parse_qsl(self.qs_on_post, self.keep_blank_values, self.strict_parsing):
  661.                 self.list.append(MiniFieldStorage(key, value))
  662.             
  663.             FieldStorageClass = None
  664.         
  665.         if not self.FieldStorageClass:
  666.             pass
  667.         klass = self.__class__
  668.         part = klass(self.fp, { }, ib, environ, keep_blank_values, strict_parsing)
  669.         while not part.done:
  670.             headers = rfc822.Message(self.fp)
  671.             part = klass(self.fp, headers, ib, environ, keep_blank_values, strict_parsing)
  672.             self.list.append(part)
  673.         self.skip_lines()
  674.  
  675.     
  676.     def read_single(self):
  677.         '''Internal: read an atomic part.'''
  678.         if self.length >= 0:
  679.             self.read_binary()
  680.             self.skip_lines()
  681.         else:
  682.             self.read_lines()
  683.         self.file.seek(0)
  684.  
  685.     bufsize = 8192
  686.     
  687.     def read_binary(self):
  688.         '''Internal: read binary data.'''
  689.         self.file = self.make_file('b')
  690.         todo = self.length
  691.         if todo >= 0:
  692.             while todo > 0:
  693.                 data = self.fp.read(min(todo, self.bufsize))
  694.                 if not data:
  695.                     self.done = -1
  696.                     break
  697.                 
  698.                 self.file.write(data)
  699.                 todo = todo - len(data)
  700.         
  701.  
  702.     
  703.     def read_lines(self):
  704.         '''Internal: read lines until EOF or outerboundary.'''
  705.         self.file = self._FieldStorage__file = StringIO()
  706.         if self.outerboundary:
  707.             self.read_lines_to_outerboundary()
  708.         else:
  709.             self.read_lines_to_eof()
  710.  
  711.     
  712.     def __write(self, line):
  713.         if self._FieldStorage__file is not None:
  714.             if self._FieldStorage__file.tell() + len(line) > 1000:
  715.                 self.file = self.make_file('')
  716.                 self.file.write(self._FieldStorage__file.getvalue())
  717.                 self._FieldStorage__file = None
  718.             
  719.         
  720.         self.file.write(line)
  721.  
  722.     
  723.     def read_lines_to_eof(self):
  724.         '''Internal: read lines until EOF.'''
  725.         while None:
  726.             line = self.fp.readline(65536)
  727.             if not line:
  728.                 self.done = -1
  729.                 break
  730.             
  731.             continue
  732.             return None
  733.  
  734.     
  735.     def read_lines_to_outerboundary(self):
  736.         '''Internal: read lines until outerboundary.'''
  737.         next = '--' + self.outerboundary
  738.         last = next + '--'
  739.         delim = ''
  740.         last_line_lfend = True
  741.         while None:
  742.             line = self.fp.readline(65536)
  743.             if not line:
  744.                 self.done = -1
  745.                 break
  746.             
  747.             if line[:2] == '--' and last_line_lfend:
  748.                 strippedline = line.strip()
  749.                 if strippedline == next:
  750.                     break
  751.                 
  752.                 if strippedline == last:
  753.                     self.done = 1
  754.                     break
  755.                 
  756.             
  757.             odelim = delim
  758.             if line[-2:] == '\r\n':
  759.                 delim = '\r\n'
  760.                 line = line[:-2]
  761.                 last_line_lfend = True
  762.             elif line[-1] == '\n':
  763.                 delim = '\n'
  764.                 line = line[:-1]
  765.                 last_line_lfend = True
  766.             else:
  767.                 delim = ''
  768.                 last_line_lfend = False
  769.             continue
  770.             return None
  771.  
  772.     
  773.     def skip_lines(self):
  774.         '''Internal: skip lines until outer boundary if defined.'''
  775.         if not (self.outerboundary) or self.done:
  776.             return None
  777.         next = '--' + self.outerboundary
  778.         last = next + '--'
  779.         last_line_lfend = True
  780.         while None:
  781.             line = self.fp.readline(65536)
  782.             if not line:
  783.                 self.done = -1
  784.                 break
  785.             
  786.             if line[:2] == '--' and last_line_lfend:
  787.                 strippedline = line.strip()
  788.                 if strippedline == next:
  789.                     break
  790.                 
  791.                 if strippedline == last:
  792.                     self.done = 1
  793.                     break
  794.                 
  795.             
  796.             last_line_lfend = line.endswith('\n')
  797.             continue
  798.             return None
  799.  
  800.     
  801.     def make_file(self, binary = None):
  802.         """Overridable: return a readable & writable file.
  803.  
  804.         The file will be used as follows:
  805.         - data is written to it
  806.         - seek(0)
  807.         - data is read from it
  808.  
  809.         The 'binary' argument is unused -- the file is always opened
  810.         in binary mode.
  811.  
  812.         This version opens a temporary file for reading and writing,
  813.         and immediately deletes (unlinks) it.  The trick (on Unix!) is
  814.         that the file can still be used, but it can't be opened by
  815.         another process, and it will automatically be deleted when it
  816.         is closed or when the current process terminates.
  817.  
  818.         If you want a more permanent file, you derive a class which
  819.         overrides this method.  If you want a visible temporary file
  820.         that is nevertheless automatically deleted when the script
  821.         terminates, try defining a __del__ method in a derived class
  822.         which unlinks the temporary files you have created.
  823.  
  824.         """
  825.         import tempfile as tempfile
  826.         return tempfile.TemporaryFile('w+b')
  827.  
  828.  
  829.  
  830. class FormContentDict(UserDict.UserDict):
  831.     '''Form content as dictionary with a list of values per field.
  832.  
  833.     form = FormContentDict()
  834.  
  835.     form[key] -> [value, value, ...]
  836.     key in form -> Boolean
  837.     form.keys() -> [key, key, ...]
  838.     form.values() -> [[val, val, ...], [val, val, ...], ...]
  839.     form.items() ->  [(key, [val, val, ...]), (key, [val, val, ...]), ...]
  840.     form.dict == {key: [val, val, ...], ...}
  841.  
  842.     '''
  843.     
  844.     def __init__(self, environ = os.environ, keep_blank_values = 0, strict_parsing = 0):
  845.         self.dict = self.data = parse(environ = environ, keep_blank_values = keep_blank_values, strict_parsing = strict_parsing)
  846.         self.query_string = environ['QUERY_STRING']
  847.  
  848.  
  849.  
  850. class SvFormContentDict(FormContentDict):
  851.     '''Form content as dictionary expecting a single value per field.
  852.  
  853.     If you only expect a single value for each field, then form[key]
  854.     will return that single value.  It will raise an IndexError if
  855.     that expectation is not true.  If you expect a field to have
  856.     possible multiple values, than you can use form.getlist(key) to
  857.     get all of the values.  values() and items() are a compromise:
  858.     they return single strings where there is a single value, and
  859.     lists of strings otherwise.
  860.  
  861.     '''
  862.     
  863.     def __getitem__(self, key):
  864.         if len(self.dict[key]) > 1:
  865.             raise IndexError, 'expecting a single value'
  866.         len(self.dict[key]) > 1
  867.         return self.dict[key][0]
  868.  
  869.     
  870.     def getlist(self, key):
  871.         return self.dict[key]
  872.  
  873.     
  874.     def values(self):
  875.         result = []
  876.         for value in self.dict.values():
  877.             if len(value) == 1:
  878.                 result.append(value[0])
  879.                 continue
  880.             result.append(value)
  881.         
  882.         return result
  883.  
  884.     
  885.     def items(self):
  886.         result = []
  887.         for key, value in self.dict.items():
  888.             if len(value) == 1:
  889.                 result.append((key, value[0]))
  890.                 continue
  891.             result.append((key, value))
  892.         
  893.         return result
  894.  
  895.  
  896.  
  897. class InterpFormContentDict(SvFormContentDict):
  898.     '''This class is present for backwards compatibility only.'''
  899.     
  900.     def __getitem__(self, key):
  901.         v = SvFormContentDict.__getitem__(self, key)
  902.         if v[0] in '0123456789+-.':
  903.             
  904.             try:
  905.                 return int(v)
  906.             except ValueError:
  907.                 
  908.                 try:
  909.                     return float(v)
  910.                 except ValueError:
  911.                     pass
  912.                 except:
  913.                     None<EXCEPTION MATCH>ValueError
  914.                 
  915.  
  916.                 None<EXCEPTION MATCH>ValueError
  917.             
  918.  
  919.         None<EXCEPTION MATCH>ValueError
  920.         return v.strip()
  921.  
  922.     
  923.     def values(self):
  924.         result = []
  925.         for key in self.keys():
  926.             
  927.             try:
  928.                 result.append(self[key])
  929.             continue
  930.             except IndexError:
  931.                 result.append(self.dict[key])
  932.                 continue
  933.             
  934.  
  935.         
  936.         return result
  937.  
  938.     
  939.     def items(self):
  940.         result = []
  941.         for key in self.keys():
  942.             
  943.             try:
  944.                 result.append((key, self[key]))
  945.             continue
  946.             except IndexError:
  947.                 result.append((key, self.dict[key]))
  948.                 continue
  949.             
  950.  
  951.         
  952.         return result
  953.  
  954.  
  955.  
  956. class FormContent(FormContentDict):
  957.     '''This class is present for backwards compatibility only.'''
  958.     
  959.     def values(self, key):
  960.         if key in self.dict:
  961.             return self.dict[key]
  962.         return None
  963.  
  964.     
  965.     def indexed_value(self, key, location):
  966.         if key in self.dict:
  967.             if len(self.dict[key]) > location:
  968.                 return self.dict[key][location]
  969.             return None
  970.         key in self.dict
  971.         return None
  972.  
  973.     
  974.     def value(self, key):
  975.         if key in self.dict:
  976.             return self.dict[key][0]
  977.         return None
  978.  
  979.     
  980.     def length(self, key):
  981.         return len(self.dict[key])
  982.  
  983.     
  984.     def stripped(self, key):
  985.         if key in self.dict:
  986.             return self.dict[key][0].strip()
  987.         return None
  988.  
  989.     
  990.     def pars(self):
  991.         return self.dict
  992.  
  993.  
  994.  
  995. def test(environ = os.environ):
  996.     '''Robust test CGI script, usable as main program.
  997.  
  998.     Write minimal HTTP headers and dump all information provided to
  999.     the script in HTML form.
  1000.  
  1001.     '''
  1002.     global maxlen
  1003.     print 'Content-type: text/html'
  1004.     print 
  1005.     sys.stderr = sys.stdout
  1006.     
  1007.     try:
  1008.         form = FieldStorage()
  1009.         print_directory()
  1010.         print_arguments()
  1011.         print_form(form)
  1012.         print_environ(environ)
  1013.         print_environ_usage()
  1014.         
  1015.         def f():
  1016.             exec 'testing print_exception() -- <I>italics?</I>'
  1017.  
  1018.         
  1019.         def g(f = f):
  1020.             f()
  1021.  
  1022.         print '<H3>What follows is a test, not an actual exception:</H3>'
  1023.         g()
  1024.     except:
  1025.         print_exception()
  1026.  
  1027.     print '<H1>Second try with a small maxlen...</H1>'
  1028.     maxlen = 50
  1029.     
  1030.     try:
  1031.         form = FieldStorage()
  1032.         print_directory()
  1033.         print_arguments()
  1034.         print_form(form)
  1035.         print_environ(environ)
  1036.     except:
  1037.         print_exception()
  1038.  
  1039.  
  1040.  
  1041. def print_exception(type = None, value = None, tb = None, limit = None):
  1042.     if type is None:
  1043.         (type, value, tb) = sys.exc_info()
  1044.     
  1045.     import traceback as traceback
  1046.     print 
  1047.     print '<H3>Traceback (most recent call last):</H3>'
  1048.     list = traceback.format_tb(tb, limit) + traceback.format_exception_only(type, value)
  1049.     print '<PRE>%s<B>%s</B></PRE>' % (escape(''.join(list[:-1])), escape(list[-1]))
  1050.     del tb
  1051.  
  1052.  
  1053. def print_environ(environ = os.environ):
  1054.     '''Dump the shell environment as HTML.'''
  1055.     keys = environ.keys()
  1056.     keys.sort()
  1057.     print 
  1058.     print '<H3>Shell Environment:</H3>'
  1059.     print '<DL>'
  1060.     for key in keys:
  1061.         print '<DT>', escape(key), '<DD>', escape(environ[key])
  1062.     
  1063.     print '</DL>'
  1064.     print 
  1065.  
  1066.  
  1067. def print_form(form):
  1068.     '''Dump the contents of a form as HTML.'''
  1069.     keys = form.keys()
  1070.     keys.sort()
  1071.     print 
  1072.     print '<H3>Form Contents:</H3>'
  1073.     if not keys:
  1074.         print '<P>No form fields.'
  1075.     
  1076.     print '<DL>'
  1077.     for key in keys:
  1078.         print '<DT>' + escape(key) + ':',
  1079.         value = form[key]
  1080.         print '<i>' + escape(repr(type(value))) + '</i>'
  1081.         print '<DD>' + escape(repr(value))
  1082.     
  1083.     print '</DL>'
  1084.     print 
  1085.  
  1086.  
  1087. def print_directory():
  1088.     '''Dump the current directory as HTML.'''
  1089.     print 
  1090.     print '<H3>Current Working Directory:</H3>'
  1091.     
  1092.     try:
  1093.         pwd = os.getcwd()
  1094.     except os.error:
  1095.         msg = None
  1096.         print 'os.error:', escape(str(msg))
  1097.  
  1098.     print escape(pwd)
  1099.     print 
  1100.  
  1101.  
  1102. def print_arguments():
  1103.     print 
  1104.     print '<H3>Command Line Arguments:</H3>'
  1105.     print 
  1106.     print sys.argv
  1107.     print 
  1108.  
  1109.  
  1110. def print_environ_usage():
  1111.     '''Dump a list of environment variables used by CGI as HTML.'''
  1112.     print '\n<H3>These environment variables could have been set:</H3>\n<UL>\n<LI>AUTH_TYPE\n<LI>CONTENT_LENGTH\n<LI>CONTENT_TYPE\n<LI>DATE_GMT\n<LI>DATE_LOCAL\n<LI>DOCUMENT_NAME\n<LI>DOCUMENT_ROOT\n<LI>DOCUMENT_URI\n<LI>GATEWAY_INTERFACE\n<LI>LAST_MODIFIED\n<LI>PATH\n<LI>PATH_INFO\n<LI>PATH_TRANSLATED\n<LI>QUERY_STRING\n<LI>REMOTE_ADDR\n<LI>REMOTE_HOST\n<LI>REMOTE_IDENT\n<LI>REMOTE_USER\n<LI>REQUEST_METHOD\n<LI>SCRIPT_NAME\n<LI>SERVER_NAME\n<LI>SERVER_PORT\n<LI>SERVER_PROTOCOL\n<LI>SERVER_ROOT\n<LI>SERVER_SOFTWARE\n</UL>\nIn addition, HTTP headers sent by the server may be passed in the\nenvironment as well.  Here are some common variable names:\n<UL>\n<LI>HTTP_ACCEPT\n<LI>HTTP_CONNECTION\n<LI>HTTP_HOST\n<LI>HTTP_PRAGMA\n<LI>HTTP_REFERER\n<LI>HTTP_USER_AGENT\n</UL>\n'
  1113.  
  1114.  
  1115. def escape(s, quote = None):
  1116.     '''Replace special characters "&", "<" and ">" to HTML-safe sequences.
  1117.     If the optional flag quote is true, the quotation mark character (")
  1118.     is also translated.'''
  1119.     s = s.replace('&', '&')
  1120.     s = s.replace('<', '<')
  1121.     s = s.replace('>', '>')
  1122.     if quote:
  1123.         s = s.replace('"', '"')
  1124.     
  1125.     return s
  1126.  
  1127.  
  1128. def valid_boundary(s, _vb_pattern = '^[ -~]{0,200}[!-~]$'):
  1129.     import re as re
  1130.     return re.match(_vb_pattern, s)
  1131.  
  1132.